/*
 * Copyright 2010 Gal Dolber.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.unnison.framework.rebind.binder;

import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.user.rebind.SourceWriter;
import com.google.gwt.user.rebind.StringSourceWriter;

import java.util.ArrayList;
import java.util.Stack;

public class BinderContextImpl implements BinderContext {

    private final SourceWriter beforeWrappers = new StringSourceWriter();
    private final SourceWriter beforeHandler = new StringSourceWriter();
    private final SourceWriter afterHandler = new StringSourceWriter();
    private final SourceWriter afterWrappers = new StringSourceWriter();
    private final ArrayList<SourceWriter> wrappersBefore = new ArrayList<SourceWriter>();
    private final Stack<SourceWriter> wrappersAfter = new Stack<SourceWriter>();
    private final StringBuilder logger = new StringBuilder();
    private final String viewTypeName;

    @Deprecated
    private final JClassType viewInterfaceType;

    private final JMethod method;

    private final JClassType eventType;
    private final JClassType presenterType;

    @Deprecated
    private final JClassType viewType;
    private final String[] parameterGetters;

    public BinderContextImpl(JMethod method, JClassType eventType, JClassType presenterType, JClassType viewType,
        JClassType viewInterfaceType, String viewTypeName, String[] parameterGetters) {
        this.method = method;
        this.eventType = eventType;
        this.presenterType = presenterType;
        this.viewType = viewType;
        this.viewTypeName = viewTypeName;
        this.parameterGetters = parameterGetters;
        this.viewInterfaceType = viewInterfaceType;
    }

    @Override
    public void addAfterHandler(StringSourceWriter writer) {
        afterHandler.println(writer.toString());
    }

    @Override
    public void addAfterWrappers(StringSourceWriter writer) {
        afterWrappers.println(writer.toString());
    }

    @Override
    public void addBeforeHandler(StringSourceWriter writer) {
        beforeHandler.println(writer.toString());
    }

    @Override
    public void addBeforeWrappers(StringSourceWriter writer) {
        beforeWrappers.println(writer.toString());
    }

    @Override
    public void addWrapper(StringSourceWriter before, StringSourceWriter after) {
        wrappersBefore.add(before);
        wrappersAfter.push(after);
    }

    @Override
    public String build(StringSourceWriter writer) {
        StringSourceWriter build = new StringSourceWriter();

        build.print(beforeWrappers.toString());
        for (SourceWriter w : wrappersBefore) {
            build.print(w.toString());
        }
        build.print(beforeHandler.toString());
        build.print(writer.toString());
        build.print(afterHandler.toString());
        for (SourceWriter w : wrappersAfter) {
            build.print(w.toString());
        }
        build.print(afterWrappers.toString());

        return build.toString();
    }

    @Override
    public JClassType getEventType() {
        return eventType;
    }

    @Override
    public String getLog() {
        String logString = logger.toString();
        return presenterType.getQualifiedSourceName() + "." + method.getName() + ", \" + event.toDebugString() + \""
            + (logString.isEmpty() ? "" : (", with: " + logString));
    }

    @Override
    public JMethod getMethod() {
        return method;
    }

    @Override
    public String[] getParameterGetters() {
        return parameterGetters;
    }

    @Override
    public JClassType getPresenterType() {
        return presenterType;
    }

    @Deprecated
    @Override
    public JClassType getViewInterfaceType() {
        return viewInterfaceType;
    }

    @Deprecated
    @Override
    public JClassType getViewType() {
        return viewType;
    }

    @Override
    public String getViewTypeName() {
        return viewTypeName;
    }

    @Override
    public void log(String log) {
        if (logger.length() > 0) {
            logger.append(", ");
        }
        logger.append(log);
    }
}
